package com.yuandian.utils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 数据归属时间刻度工具类
 */
public class DataBelongUtil {

    /**
     * 划分数据所属时间刻度
     * @param endTime 预设最大时间刻度
     * @param type 刻度划分类型
     * @param list 数据
     * @param clazz 划分的数据类
     * @param <T> 泛型
     * @return
     */
    public static <T> Map<String, List<T>> dataBelong(String endTime, int type, List<T> list, Class<T> clazz) {

        Map<String, List<T>> map = new LinkedHashMap<>();

        String minLabelTime = "";
        List<String> labelList = generateLabelTime(endTime, type);
        for(int i = labelList.size() - 1; i >= 0; i--) {
            map.put(labelList.get(i), new ArrayList<>());
        }
        long minLabel = DateTool.yyyy_MM_dd_HH_mm_ss(labelList.get(labelList.size() - 1)).getTime() / 1000;

        try {
            Field field = clazz.getDeclaredField("cycleTime");
            field.setAccessible(true);
            for(T data : list) {
                String cycleTime = (String) field.get(data);
                long cycle = DateTool.yyyy_MM_dd_HH_mm_ss(cycleTime).getTime() / 1000;
                long label = minLabel + (cycle - minLabel) / 1800 * 1800;
                String time = DateTool.yyyy_MM_dd_HH_mm_ssBySecond(label);
                map.get(time).add(data);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 获取对应时间刻度开始时间戳
     * @param endTime
     * @param type
     * @return
     */
    public static String getMinCycleTime(String endTime, int type) {
        Date date = DateTool.yyyy_MM_dd_HH_mm_ss(endTime);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(date);
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(date);
        // 获取当天00:00:00时间戳
        if (startCalendar.get(Calendar.HOUR_OF_DAY) == 0
                && startCalendar.get(Calendar.MINUTE) == 0
                && startCalendar.get(Calendar.SECOND) == 0) {
            startCalendar.add(Calendar.DAY_OF_MONTH, -1);
        } else {
            startCalendar.set(Calendar.HOUR_OF_DAY, 0);
            startCalendar.set(Calendar.MINUTE, 0);
            startCalendar.set(Calendar.SECOND, 0);
        }

        long firstTime = startCalendar.getTimeInMillis();
        Date firstDate = startCalendar.getTime();
        if(type == TypeEnum.LABLE_ONE.value) {
            endCalendar.add(Calendar.HOUR_OF_DAY, -5);
            endCalendar.add(Calendar.MINUTE, -30);
        } else if(type == TypeEnum.LABLE_TWO.value){
            endCalendar.add(Calendar.HOUR_OF_DAY, -11);
            endCalendar.add(Calendar.MINUTE, -30);
        }

        // 如果小于00:00:00则返回 00:00:00
        if (firstTime > endCalendar.getTimeInMillis()) {
            return DateTool.yyyy_MM_dd_HH_mm_ss(firstDate);
        }

        return DateTool.yyyy_MM_dd_HH_mm_ss(endCalendar.getTime());
    }

    /**
     * 根据结束时间及刻度类型生成时间刻度
     * @param endTime
     * @param type
     * @return
     */
    private static List<String> generateLabelTime(String endTime, int type) {
        List<String> dateList = new ArrayList<>();

        Date date = DateTool.yyyy_MM_dd_HH_mm_ss(endTime);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 获取当天00:00:00时间戳
        if (calendar.get(Calendar.HOUR_OF_DAY) == 0
                && calendar.get(Calendar.MINUTE) == 0
                && calendar.get(Calendar.SECOND) == 0) {
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        } else {
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        }
        long firstTime = calendar.getTimeInMillis();

        int labelLength = 0;
        if(type == TypeEnum.LABLE_ONE.value) {
            calendar.set(Calendar.HOUR_OF_DAY, 5);
            calendar.set(Calendar.MINUTE, 30);
            labelLength = TypeEnum.LABLE_ONE.length;
        } else if(type == TypeEnum.LABLE_TWO.value){
            calendar.set(Calendar.HOUR_OF_DAY, 11);
            calendar.set(Calendar.MINUTE, 30);
            labelLength = TypeEnum.LABLE_TWO.length;
        }
        long time = date.getTime() > calendar.getTimeInMillis() ? date.getTime() : calendar.getTimeInMillis();
        calendar.setTimeInMillis(time);
        while (labelLength > 0) {
            dateList.add(DateTool.yyyy_MM_dd_HH_mm_ss(calendar.getTime()));
            calendar.add(Calendar.MINUTE, -30);
            labelLength-- ;
        }
        return dateList;
    }

    public static <T> List<T> dataBelongForTypeThree(String endTime, List<T> list, Class<T> clazz) {
        Date date = DateTool.yyyy_MM_dd_HH_mm_ss(endTime);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        List<String> dateList = new ArrayList<>();
        int labelLength = TypeEnum.LABLE_THREE.length;
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        while (labelLength > 0) {
            dateList.add(0, DateTool.yyyy_MM_dd_HH_mm_ss(calendar.getTime()));
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            labelLength--;
        }

        List<T> result = new ArrayList<>();
        try {
            Field field = clazz.getDeclaredField("cycleTime");
            field.setAccessible(true);
            for (int i = 0; i < dateList.size(); i++) {
                String d = dateList.get(i);
                for (int j = 0; j < list.size(); j++) {
                    String cycleTime = (String) field.get(list.get(j));
                    cycleTime = cycleTime.substring(0, 19);
                    if (d.equals(cycleTime)) {
                        result.add(i, list.get(j));
                        break;
                    }
                    if (j == list.size() - 1) {
                        T t = clazz.newInstance();
                        field.set(t, d);
                        result.add(i, t);
                    }
                }
            }
        } catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return result;
    }

    public enum TypeEnum {

        LABLE_ONE(1, "刻度一", 12),
        LABLE_TWO(2, "刻度二", 24),
        LABLE_THREE(3, "刻度三", 11);

        private int value;
        private String remark;
        private int length;

        TypeEnum(int value, String remark, int length) {
            this.value = value;
            this.remark = remark;
            this.length = length;
        }
    }

//    public static void main(String[] args) {
//        List<BusiStepStatMEo> list = new ArrayList<>();
//        BusiStepStatMEo eo = new BusiStepStatMEo();
//        eo.setCycleTime("2021-04-08 09:44:00");
//        list.add(eo);
//        BusiStepStatMEo eo1 = new BusiStepStatMEo();
//        eo1.setCycleTime("2021-04-08 12:33:00");
//        list.add(eo1);
//
//        try {
//            Map<String, List<BusiStepStatMEo>> map = dataBelong("2021-04-08 15:12:00", 1, list, BusiStepStatMEo.class);
//            map.forEach((key, value) -> {
//                System.out.print(key + ":" + "[");
//                value.forEach(item -> System.out.print(item.getCycleTime()));
//                System.out.println("]");
//            });
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
}
